home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / ARCADE.ZIP / MS.EXE / lzh / ARC8_2.CHP < prev    next >
Encoding:
Text File  |  1993-06-15  |  60.3 KB  |  1,861 lines

  1. %
  2. #EF
  3. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 26
  4. #HS,1,4,80,25,11,1
  5. #C4,R5
  6.                            ~W~IImplementing Attackers~Y~I
  7.  
  8. Now we have enough to write the code for an attacker, after which, we'll
  9. write enough of the game to get the attacker functioning. The header file
  10. ~G~IATTACKER.H~Y~I will contain the type definition, macros, and prototypes we'll
  11. need for the attacker. Let's look at that first.
  12.  
  13. #WN
  14. %
  15. #EF
  16. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 27
  17. #HS,1,4,80,25,11,1
  18. #C1,R5
  19.                                  ~W~I Listing 8.5~Y~I
  20.                                   ATTACKER.H
  21.  
  22.  /*------------------------------attacker.h-----------------------------------*/
  23.  /*
  24.  Copyright 1992 David Conger
  25.  */
  26.  
  27.  #ifndef __ATTACKER_H__
  28.  
  29.  /*-----------------------------include files--------------------------------*/
  30.  
  31. ~W~I #include "game.h"
  32.  #include "charactr.h"~Y~I
  33.  
  34.  /*---------------------------end include files------------------------------*/
  35.  
  36. #C1,R23
  37.                              ~C~IContinued On Next Page~Y~I
  38.  
  39. #BO,4,7,78,11,7,1,0,3,0,7
  40. The attacker makes use of the types boolean and character. These are
  41. defined in GAME.H and CHARACTR.H respectively, so both files are
  42. included in ATTACKER.H.
  43.  
  44. #WP
  45. %
  46. #EF
  47. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 28
  48. #HS,1,4,80,25,11,1
  49. #C1,R5
  50.                              ~W~I Listing 8.5 (cont)~Y~I
  51.                                   ATTACKER.H
  52.  
  53.  
  54.  
  55.  /*----------------------------type definitions------------------------------*/
  56.  
  57. ~W~I typedef enum {ATTACKER_LEFT,ATTACKER_RIGHT,ATTACKER_DOWN} attacker_direction;~Y~I
  58.  
  59.  typedef struct
  60.  {
  61.      attacker_direction current_direction;
  62.      character critter;
  63.      boolean at_edge;
  64.  } attacker;
  65.  
  66. /*--------------------------end type definitions----------------------------*/
  67.  
  68. #C1,R23
  69.                              ~C~IContinued On Next Page~Y~I
  70.  
  71. #BO,4,17,78,23,7,1,0,5,0,7
  72. An attacker, like a player, has a direction that it is moving in at
  73. all times. Unlike a player, an attacker may never stand still and it
  74. may move down. It is for this reason that a different enumerated type,
  75. attacker_direction, was defined for attackers rather than reuse the
  76. same one that was used for a player in Listing 8.1.
  77.  
  78. #C1,R10
  79. ~Y~I /*----------------------------type definitions------------------------------*/
  80.  
  81.  typedef enum {ATTACKER_LEFT,ATTACKER_RIGHT,ATTACKER_DOWN} attacker_direction;
  82.  
  83. ~W~I typedef struct
  84.  {
  85.      attacker_direction current_direction;
  86.      character critter;
  87.      boolean at_edge;
  88.  } attacker;~Y~I
  89.  
  90. /*--------------------------end type definitions----------------------------*/
  91.  
  92.  
  93. #BO,4,5,78,11,7,1,0,5,0,7
  94. The attacker structure is just as we saw it in the last chapter.
  95. Remember that the only attackers that can fire their bullets are
  96. those which have no other attacker immediately below them. The
  97. member at_edge, tells us whether or not a particular attacker is in
  98. a position to fire.
  99.  
  100. #WP
  101. %
  102. #EF
  103. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 29
  104. #HS,1,4,80,25,11,1
  105. #C1,R5
  106.                              ~W~I Listing 8.5 (cont)~Y~I
  107.                                   ATTACKER.H
  108.  
  109. /*--------------------------------macros-----------------------------------*/
  110.  
  111.  #define set_attacker_col(atkr,atkrcol) \
  112.              set_character_col(atkr->critter,atkrcol)
  113.  
  114.  #define set_attacker_row(atkr,atkrrow)    \
  115.              set_character_row(atkr->critter,atkrrow)
  116.  
  117.  #define set_attacker_position(atkr,atkr_row,atkr_col) \
  118.              set_character_position(atkr->critter,atkr_row,atkr_col)
  119.  
  120.  #define set_attacker_direction(atkr,atkr_dir) \
  121.              atkr->current_direction=atkr_dir
  122.  
  123. #C1,R23
  124.                              ~C~IContinued On Next Page~Y~I
  125.  
  126. #BO,40,10,78,17,7,1,0,6,0,7
  127. The next few pages of Listing 8.5
  128. contain the macros that implement
  129. many of the operations that can be
  130. performed on an attacker. The
  131. majority of these are just calls to
  132. character macros and point macros.
  133.  
  134. #WP
  135. %
  136. #EF
  137. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 30
  138. #HS,1,4,80,25,11,1
  139. #C1,R5
  140.                              ~W~I Listing 8.5 (cont)~Y~I
  141.                                   ATTACKER.H
  142.  
  143.  #define set_attacker_at_edge(atkr,t_f)  atkr->at_edge=t_f
  144.  
  145.  #define set_attacker_bullet_color(atkr,bcolor) \
  146.              set_character_bullet_color(atkr->critter,bcolor)
  147.  
  148.  #define set_attacker_bullet_direction(atkr,adir) \
  149.              set_character_bullet_direction(atkr->critter,adir)
  150.  
  151.  #define set_attacker_bullet(atkr,t_f) \
  152.              set_character_bullet(atkr->critter,t_f)
  153.  
  154.  #define set_attacker_bullet_row(atkr,br) \
  155.              set_character_bullet_row(atkr->critter,(br))
  156.  
  157.  
  158. #C1,R23
  159.                              ~C~IContinued On Next Page~Y~I
  160.  
  161. #WP
  162. %
  163. #EF
  164. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 31
  165. #HS,1,4,80,25,11,1
  166. #C1,R5
  167.                              ~W~I Listing 8.5 (cont)~Y~I
  168.                                   ATTACKER.H
  169.  
  170.  #define set_attacker_bullet_col(atkr,bc) \
  171.              set_character_bullet_col(atkr->critter,(bc))
  172.  
  173.  #define set_attacker_bitmap(atkr,bmap)    \
  174.              set_character_bitmap(atkr->critter,bmap)
  175.  
  176.  #define set_attacker_bitmap_height(atkr,ahi) \
  177.              set_character_bitmap_height(atkr->critter,ahi)
  178.  
  179.  #define set_attacker_bitmap_width(atkr,awi) \
  180.              set_character_bitmap_width(atkr->critter,awi)
  181.  
  182.  
  183. #C1,R23
  184.                              ~C~IContinued On Next Page~Y~I
  185.  
  186. #WP
  187. %
  188. #EF
  189. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 32
  190. #HS,1,4,80,25,11,1
  191. #C1,R5
  192.                              ~W~I Listing 8.5 (cont)~Y~I
  193.                                   ATTACKER.H
  194.  
  195.  #define set_attacker_is_alive(atkr,t_f) \
  196.              set_character_is_alive(atkr->critter,t_f)
  197.  
  198.  #define set_attacker_move_increment(atkr,mi) \
  199.              set_character_move_increment(atkr->critter,mi)
  200.  
  201.  #define get_attacker_row(atkr) \
  202.              get_character_row(atkr->critter)
  203.  
  204.  #define get_attacker_col(atkr) \
  205.              get_character_col(atkr->critter)
  206.  
  207. #C1,R23
  208.                              ~C~IContinued On Next Page~Y~I
  209.  
  210. #WP
  211. %
  212. #EF
  213. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 33
  214. #HS,1,4,80,25,11,1
  215. #C1,R5
  216.                              ~W~I Listing 8.5 (cont)~Y~I
  217.                                   ATTACKER.H
  218.  
  219.  #define get_attacker_move_increment(atkr) \
  220.              get_character_move_increment(atkr->critter)
  221.  
  222.  #define get_attacker_bullet(atkr)  get_character_bullet(atkr->critter)
  223.  
  224.  #define get_attacker_bullet_row(atkr) \
  225.              get_character_bullet_row(atkr->critter)
  226.  
  227.  #define get_attacker_bullet_col(atkr) \
  228.              get_character_bullet_col(atkr->critter)
  229.  
  230. #C1,R23
  231.                              ~C~IContinued On Next Page~Y~I
  232.  
  233. #WP
  234. %
  235. #EF
  236. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 34
  237. #HS,1,4,80,25,11,1
  238. #C1,R5
  239.                              ~W~I Listing 8.5 (cont)~Y~I
  240.                                   ATTACKER.H
  241.  
  242.  #define get_attacker_has_bullet(atkr) \
  243.              get_character_has_bullet(atkr->critter)
  244.  
  245.  #define get_attacker_bullet_color(atkr) \
  246.              get_character_bullet_color(atkr->critter)
  247.  
  248.  #define get_attacker_bitmap(atkr) \
  249.              get_character_bitmap(atkr->critter)
  250.  
  251.  #define get_attacker_bitmap_height(atkr) \
  252.              get_character_bitmap_height(atkr->critter)
  253.  
  254.  #define get_attacker_bitmap_width(atkr) \
  255.              get_character_bitmap_width(atkr->critter)
  256.  
  257. #C1,R23
  258.                              ~C~IContinued On Next Page~Y~I
  259.  
  260. #WP
  261. %
  262. #EF
  263. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 35
  264. #HS,1,4,80,25,11,1
  265. #C1,R5
  266.                              ~W~I Listing 8.5 (cont)~Y~I
  267.                                   ATTACKER.H
  268.  
  269.  
  270.  #define get_attacker_is_alive(atkr) \
  271.              get_character_is_alive(atkr->critter)
  272.  
  273.  #define get_attacker_direction(atkr) atkr->current_direction
  274.  
  275.  #define get_attacker_at_edge(atkr)  atkr->at_edge
  276.  
  277.  /*------------------------------end macros---------------------------------*/
  278.  
  279.  
  280. #C1,R23
  281.                              ~C~IContinued On Next Page~Y~I
  282.  
  283. #WP
  284. %
  285. #EF
  286. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 36
  287. #HS,1,4,80,25,11,1
  288. #C1,R5
  289.                              ~W~I Listing 8.5 (cont)~Y~I
  290.                                   ATTACKER.H
  291.  
  292.  /*------------------------------Prototypes---------------------------------*/
  293.  
  294.  void init_attackers(attacker *badie,int rows_of_attackers,
  295.                      int cols_of_attackers,
  296.                      int init_up_left_row,int init_up_left_col,
  297.                      int distance_between_rows,int
  298.                      distance_between_attackers,
  299.                      attacker_direction init_direction,int
  300.                      move_increment,
  301.                      bitmap image,int image_height,int image_width);
  302.  
  303.  void draw_attackers(attacker *meanies,
  304.                      int rows_of_attackers,
  305.                      int cols_of_attackers);
  306.  
  307. #C1,R23
  308.                              ~C~IContinued On Next Page~Y~I
  309.  
  310. #BO,4,17,78,20,7,1,0,2,0,7
  311. The rest of the operations that can be performed on an attacker are
  312. found in the functions whose prototypes at the end of Listing 8.5.
  313.  
  314. #WP
  315. %
  316. #EF
  317. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 37
  318. #HS,1,4,80,25,11,1
  319. #C1,R5
  320.                              ~W~I Listing 8.5 (cont)~Y~I
  321.                                   ATTACKER.H
  322.  
  323.  void shoot_attacker_gun(attacker *nasties,
  324.                          int rows_of_attackers,
  325.                          int cols_of_attackers);
  326.  
  327.  boolean move_attacker_row(attacker *nasties,int rows_of_attackers,
  328.                            int cols_of_attackers,
  329.                            int *current_row);
  330.  
  331.  boolean attackers_all_dead(attacker *thugs,
  332.                             int rows_of_attackers,
  333.                             int cols_of_attackers);
  334.  
  335.  void draw_an_attacker(attacker *thug,int operation);
  336.  
  337. #C1,R23
  338.                              ~C~IContinued On Next Page~Y~I
  339.  
  340. #WP
  341. %
  342. #EF
  343. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 38
  344. #HS,1,4,80,25,11,1
  345. #C1,R5
  346.                              ~W~I Listing 8.5 (cont)~Y~I
  347.                                   ATTACKER.H
  348.  
  349.  void erase_an_attacker(attacker *thug);
  350.  
  351.  /*----------------------------End prototypes-------------------------------*/
  352.  
  353.  
  354.  #define __ATTACKER_H__
  355.  #endif
  356.  
  357.  /*------------------------------attacker.h-----------------------------------*/
  358.  
  359. #WP
  360. %
  361. #EF
  362. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 39
  363. #HS,1,4,80,25,11,1
  364. #C4,R5
  365. ~Y~I
  366. One of the drawbacks with accessing several nested structures through
  367. macro interfaces is very apparent in ~G~IATTACKER.H~Y~I. Notice that, since an
  368. attacker has a character in it, macros must be provided that give access
  369. to the fields in the character member. These macros almost duplicate the
  370. macros in ~G~ICHARACTR.H~Y~I. The character structure, in turn, contains a point.
  371. In order to provide access to the members of the point that are in the
  372. character, we've got to produce more macros.
  373.  
  374. #WN
  375. The upshot of all of this is that using this type of interface is forcing
  376. us to write a lot of macros. In an object oriented language that supports
  377. inheritance like C++, this would not be the case. However, in C we can't
  378. avoid this problem if we want to gain the kind of flexibility and
  379. maintainability that this style of programming provides.
  380.  
  381. #WN
  382. The functions that perform the more complex operations on an attacker are
  383. contained in ~G~IATTACKER.C~Y~I, which is shown in Listing 8.6.
  384.  
  385. #WP
  386. %
  387. #EF
  388. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 40
  389. #HS,1,4,80,25,11,1
  390. #C1,R5
  391.                                      ~W~IListing 8.6~Y~I
  392.                                      ATTACKER.C
  393.  
  394.  /*-----------------------------attacker.c-----------------------------------*/
  395.  /*
  396.  Copyright 1992 David Conger
  397.  */
  398.  
  399.  /*-----------------------------include files--------------------------------*/
  400.  
  401. ~W~I #include "game.h"
  402.  #include "attacker.h"
  403.  #include "bullet.h"
  404.  #include "charactr.h"
  405.  #include <graphics.h>
  406.  #include "noises.h"~Y~I
  407.  
  408.  /*---------------------------end include files------------------------------*/
  409.  
  410.  
  411.  
  412. #C1,R23
  413.                              ~C~IContinued On Next Page~Y~I
  414.  
  415. #BO,4,7,78,10,7,1,0,2,0,7
  416. ATTACKER.C starts off by including the header files that are necessary
  417. to its operation.
  418.  
  419.  
  420. #WP
  421. %
  422. #EF
  423. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 41
  424. #HS,1,4,80,25,11,1
  425. #C1,R5
  426.                                  ~W~IListing 8.6 (cont)~Y~I
  427.                                      ATTACKER.C
  428.  
  429.  /*----------------------------local prototypes------------------------------*/
  430.  
  431. ~W~I static void set_all_attacker_direction(attacker *thugs,int rows_of_attackers,
  432.                                         int cols_of_attackers,
  433.                                         attacker_direction dir);
  434. ~Y~I
  435.  /*--------------------------end local prototypes----------------------------*/
  436.  
  437.  
  438. #C1,R23
  439.                              ~C~IContinued On Next Page~Y~I
  440.  
  441.  
  442. #BO,4,17,78,22,7,1,0,4,0,7
  443. The next step is to declare the prototype for a static function. This
  444. function is used only in this file so it is made static. This is in
  445. keeping with the ideas of information and implementation hiding that
  446. we discussed in Chapter 5.
  447.  
  448. #BO,4,17,78,22,7,1,0,4,0,7
  449. I often tell my students that we need to hide things better than the
  450. CIA. We should only make information and implementation available on a
  451. "need to know" basis. If a function is only used in a single C source
  452. file, it should be static so that it is visible only in that  file.
  453.  
  454. #BO,4,17,78,20,7,1,0,2,0,7
  455. If it is needed by more than one file, then the storage class should
  456. not be static, and its prototype should be put in a header file.
  457.  
  458. #WP
  459. %
  460. #EF
  461. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 42
  462. #HS,1,4,80,25,11,1
  463. #C1,R5
  464.                                  ~W~IListing 8.6 (cont)~Y~I
  465.                                      ATTACKER.C
  466.  
  467.  /*-----------------------------init_attackers-------------------------------*/
  468.  
  469.  void init_attackers(attacker *badie,int rows_of_attackers,
  470.                      int cols_of_attackers,
  471.                      int init_up_left_row,int init_up_left_col,
  472.                      int distance_between_rows,
  473.                      int distance_between_attackers,
  474.                      attacker_direction init_direction,int move_increment,
  475.                      bitmap image,int image_height,int image_width)
  476.  {
  477.      int i,j;
  478.      attacker *temp;
  479.  
  480. #C1,R23
  481.                              ~C~IContinued On Next Page~Y~I
  482.  
  483. #BO,4,17,78,20,7,1,0,2,0,7
  484. The first function in Listing 8.6 is init_attackers(). This function
  485. initializes the fields in a two dimensional array of attackers.
  486.  
  487. #WP
  488. %
  489. #EF
  490. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 43
  491. #HS,1,4,80,25,11,1
  492. #C1,R4
  493.                                  ~W~IListing 8.6 (cont)~Y~I
  494.                                      ATTACKER.C
  495.      for (i=0;i<rows_of_attackers;i++)
  496.      {
  497.          for(j=0;j<cols_of_attackers;j++)
  498.          {
  499.              temp=badie + (i*cols_of_attackers) + j;
  500.              set_attacker_bullet(temp,FALSE);
  501.              set_attacker_is_alive(temp,TRUE);
  502.              set_attacker_bitmap(temp,image);
  503.              set_attacker_row(temp,
  504.                               init_up_left_row+(i*distance_between_rows));
  505.              set_attacker_col(temp,
  506.                               init_up_left_col+(j*distance_between_attackers));
  507.              set_attacker_direction(temp,init_direction);
  508.              set_attacker_move_increment(temp,move_increment);
  509.              set_attacker_bitmap_height(temp,image_height);
  510.              set_attacker_bitmap_width(temp,image_width);
  511.              set_attacker_at_edge(temp,FALSE);
  512.          }
  513.      }
  514.  
  515. #BO,4,17,78,23,7,1,0,5,0,7
  516. These lines show a pair of nested for loops that go through the 2D
  517. array row by row and column by column, initializing the structures
  518. with the parameter values that were passed to the function. As
  519. always, we are using the macro interface to store values into the
  520. structures rather than refer to the structure members directly.
  521.  
  522.  
  523. #C1,R10
  524. ~W~I             temp=badie + (i*cols_of_attackers) + j;~Y~I
  525.  
  526. #BO,4,17,78,20,7,1,0,2,0,7
  527. If you're not familiar with using pointer notation to index into a 2D
  528. array, this line can look a little odd.
  529.  
  530.  
  531. #BO,4,16,78,23,7,1,0,6,0,7
  532. This instruction sets a pointer called "temp" to point at each attacker
  533. in the array. The variable "i" is the current row number, "j" is the
  534. column number. By multiplying "i" times the width of a row (the width
  535. of a row is the number of columns per row), we index our pointer to the
  536. beginning of each row in the array. By adding the current column number,
  537. we can access each attacker in the current row one by one.
  538.  
  539. #C1,R10
  540. ~Y~I             temp=badie + (i*cols_of_attackers) + j;
  541. ~W~I             set_attacker_bullet(temp,FALSE);~Y~I
  542.  
  543. #BO,4,17,78,21,7,1,0,3,0,7
  544. There are only three fields in each structure that are not set to values
  545. that are passed into this function as parameters. The first of these
  546. fields tell the attacker that it doesn't have a bullet.
  547.  
  548. #C1,R11
  549. ~Y~I             set_attacker_bullet(temp,FALSE);
  550. ~W~I             set_attacker_is_alive(temp,TRUE);~Y~I
  551.  
  552. #BO,4,17,78,19,7,1,0,1,0,7
  553. Here we tell the attacker that it is alive.
  554.  
  555. #C1,R12
  556. ~Y~I             set_attacker_is_alive(temp,TRUE);
  557.  
  558. #C1,R22
  559. ~W~I             set_attacker_at_edge(temp,FALSE);~Y~I
  560.  
  561. #BO,4,7,78,12,7,1,0,4,0,7
  562. This tells the attacker that it is on the edge of its column. By
  563. default, the attacker is assumed at initialization to have no bullet,
  564. to be alive, and to be somewhere other than at the edge of its
  565. column.
  566.  
  567. #BO,4,7,78,11,7,1,0,3,0,7
  568. The attackers that actually are at the edge, however, need to be told
  569. otherwise. Attackers are at the edge of their columns when where is no
  570. attacker immediately below them.
  571.  
  572. #WP
  573. %
  574. #EF
  575. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 44
  576. #HS,1,4,80,25,11,1
  577. #C1,R5
  578.                                  ~W~IListing 8.6 (cont)~Y~I
  579.                                      ATTACKER.C
  580.  
  581.      temp=badie+((rows_of_attackers-1)*cols_of_attackers);
  582.      for (i=0;i<cols_of_attackers;i++,temp++)
  583.          set_attacker_at_edge(temp,TRUE);
  584.  }
  585.  
  586.  /*---------------------------end init_attackers-----------------------------*/
  587.  
  588.  
  589. #C1,R23
  590.                              ~C~IContinued On Next Page~Y~I
  591.  
  592. #BO,4,17,78,21,7,1,0,3,0,7
  593. Initially, the only attackers that are at the edge of their columns are
  594. those in the bottom row. These are the ones that must be told they can
  595. fire.
  596.  
  597. #C1,R5
  598.                                  ~W~IListing 8.6 (cont)~Y~I
  599.                                      ATTACKER.C
  600.  
  601. ~W~I     temp=badie+((rows_of_attackers-1)*cols_of_attackers);~Y~I~N
  602.  
  603. #BO,4,17,78,20,7,1,0,2,0,7
  604. First, the pointer "temp" needs to be pointed at the beginning of the
  605. bottom row of attackers.
  606.  
  607. #C1,R5
  608.                                  ~W~IListing 8.6 (cont)~Y~I
  609.                                      ATTACKER.C
  610.  
  611.      temp=badie+((rows_of_attackers-1)*cols_of_attackers);
  612. ~W~I     for (i=0;i<cols_of_attackers;i++,temp++)
  613.          set_attacker_at_edge(temp,TRUE);~Y~I
  614.  
  615. #BO,4,17,78,20,7,1,0,2,0,7
  616. Next, we go into a loop that marches down the row and tells each
  617. attacker in that row that it is on bottom.
  618.  
  619. #BO,4,17,78,20,7,1,0,2,0,7
  620. Once this loop is complete,the no more initializations need to be
  621. done, so the function returns.
  622.  
  623. #WP
  624. %
  625. #EF
  626. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 45
  627. #HS,1,4,80,25,11,1
  628. #C1,R4
  629.                                  ~W~IListing 8.6 (cont)~Y~I
  630.                                      ATTACKER.C
  631.  /*----------------------------draw_attackers--------------------------------*/
  632.  void draw_attackers(attacker *meanies,int rows_of_attackers,
  633.                      int cols_of_attackers)
  634.  {
  635.      int i,j;
  636.      attacker *temp=meanies;
  637.      for (i=0;i<rows_of_attackers;i++)
  638.      {
  639.          for (j=0;j<cols_of_attackers;j++)
  640.          {
  641.              if (get_attacker_is_alive(temp))
  642.                  draw_an_attacker(temp,COPY_PUT);
  643.              temp++;
  644.          }
  645.      }
  646.  }
  647.  /*--------------------------end draw_attackers------------------------------*/
  648.  
  649. #C1,R24
  650.                              ~C~IContinued On Next Page~Y~I
  651.  
  652. #BO,4,17,78,21,7,1,0,3,0,7
  653. The next function in Listing 8.6 is draw_attackers(). The purpose of
  654. this function is to be able to draw the entire array of attackers with
  655. one function call. It takes three parameters.
  656.  
  657. #C1,R7
  658.  void draw_attackers(~W~Iattacker *meanies~Y~I,int rows_of_attackers,
  659.                      int cols_of_attackers)
  660.  
  661. #BO,4,17,78,19,7,1,0,1,0,7
  662. The first is a pointer to the array of attackers.
  663.  
  664. #C1,R7
  665.  void draw_attackers(attacker *meanies,~W~Iint rows_of_attackers~Y~I,
  666.                      ~W~Iint cols_of_attackers~Y~I)
  667.  
  668. #BO,4,17,78,20,7,1,0,2,0,7
  669. The second and third parameters are the number of rows and columns in
  670. the array respectively.
  671.  
  672. #BO,4,14,78,23,7,1,0,8,0,7
  673. We could, if we wanted to, specify the size of the array with named
  674. constants in the declaration of the first parameter. If we did, the
  675. prototype for this function would look like what is shown below.
  676.  
  677. void draw_attackers(
  678.     attacker meanies[ROWS_OF_ATTACKERS][COLS_OF_ATTACKERS]);
  679.  
  680. By doing this, we have eliminated two parameters.
  681.  
  682.  
  683. #BO,4,15,78,23,7,1,0,7,0,7
  684. That's ok if we're always going to have the same number of rows and
  685. columns of attackers (that's what we're doing in this game). However,
  686. one of the possible improvements you might want to make to the game is
  687. to have a few different arrays of attackers, each of different size.
  688. At lower levels of play, there would probably be fewer attackers. As
  689. the user moved to higher levels in the game, he/she could be presented
  690. with more attackers on the screen to shoot.
  691.  
  692. #BO,4,17,78,22,7,1,0,4,0,7
  693. If we had written the code for a fixed sized array, it would have made
  694. this enhancement harder to do. Remember, maintenance (which includes
  695. enhancements) is the most costly part of the software life cycle.
  696. Anything we can do to plan ahead will help.
  697.  
  698. #C1,R7
  699.  void draw_attackers(attacker *meanies,int rows_of_attackers,
  700.                      int cols_of_attackers)
  701.  {
  702.      int i,j;
  703.      ~W~Iattacker *temp=meanies~Y~I;
  704.  
  705. #BO,4,17,78,21,7,1,0,3,0,7
  706. The draw_attackers() function is fairly simple. On this line, a
  707. temporary working pointer is created and set to point at the
  708. beginning of the array of attackers.
  709.  
  710. #C1,R11
  711.      attacker *temp=meanies;
  712. ~W~I     for (i=0;i<rows_of_attackers;i++)
  713.      {
  714.          for (j=0;j<cols_of_attackers;j++)
  715.          {
  716.              if (get_attacker_is_alive(temp))
  717.                  draw_an_attacker(temp,COPY_PUT);
  718.              temp++;
  719.          }
  720.      }~Y~I
  721.  
  722. #BO,4,4,78,10,7,1,0,5,0,7
  723. These two nested loops step through the array, attacker by attacker.
  724. Each attacker is asked if it is alive. If it is, it is drawn. If it
  725. isn't, it is skipped. Video games are the only place you can ask
  726. someone if they're alive, get a negative answer, and have it be
  727. accurate.
  728.  
  729. #C1,R12
  730. ~Y~I     for (i=0;i<rows_of_attackers;i++)
  731.      {
  732.          for (j=0;j<cols_of_attackers;j++)
  733.          {
  734.              if (get_attacker_is_alive(temp))
  735. ~W~I                 draw_an_attacker(temp,COPY_PUT);~Y~I
  736.              temp++;
  737.          }
  738.      }
  739.  
  740. #BO,4,7,78,9,7,1,0,1,0,7
  741. Each attacker is drawn by calling the function draw_an_attacker().
  742.  
  743. #WP
  744. %
  745. #EF
  746. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 46
  747. #HS,1,4,80,25,11,1
  748. #C1,R5
  749.                                  ~W~IListing 8.6 (cont)~Y~I
  750.                                      ATTACKER.C
  751.  
  752.  
  753. /*---------------------------draw_an_attacker-------------------------------*/
  754.  
  755. void draw_an_attacker(attacker *thug,int operation)
  756. {
  757.     putimage(get_attacker_col(thug),get_attacker_row(thug),
  758.              get_attacker_bitmap(thug),operation);
  759. }
  760.  
  761. /*-------------------------end draw_an_attacker-----------------------------*/
  762.  
  763.  
  764. #C1,R23
  765.                              ~C~IContinued On Next Page~Y~I
  766.  
  767. #BO,4,14,78,23,7,1,0,8,0,7
  768. This function is just a call to the BGI graphics library function
  769. putimage(). Usually, I would have made this function to be of
  770. storage class static, since it is called only by functions in this
  771. file. However, it occurred to me that, as an enhancement, you might
  772. want to make a rogue attacker - one that wanders around the screen
  773. independently of the array of attackers. This would be a great
  774. challenge for the user, especially at higher levels of play.
  775. Therefore, I didn't make the function static.
  776.  
  777. #WP
  778. %
  779. #EF
  780. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 47
  781. #HS,1,4,80,25,11,1
  782. #C1,R5
  783.                                  ~W~IListing 8.6 (cont)~Y~I
  784.                                      ATTACKER.C
  785.  
  786. /*-----------------------------move_attacker_row----------------------------*/
  787.  
  788. boolean move_attacker_row(attacker *nasties,int rows_of_attackers,
  789.                           int cols_of_attackers,
  790.                           int *current_row)
  791. {
  792.     int i,j;
  793.     attacker *temp=nasties+(*current_row * cols_of_attackers);
  794.     static attacker_direction go_to=ATTACKER_RIGHT;
  795.     static int maxy=0;
  796.     boolean still_in_play=TRUE;
  797.  
  798.  
  799. #C1,R23
  800.                              ~C~IContinued On Next Page~Y~I
  801.  
  802. #BO,4,17,78,20,7,1,0,2,0,7
  803. The function move_attacker_row() is next. The purpose of the function
  804. is to move a row of attackers in the appropriate direction.
  805.  
  806. #C1,R10
  807. ~W~Iboolean ~Y~Imove_attacker_row(attacker *nasties,int rows_of_attackers,
  808.  
  809. #BO,4,17,78,23,7,1,0,5,0,7
  810. The return type of this function is boolean. If the row, or any
  811. attacker in the row, moves out of play, this function returns FALSE.
  812. If it is still in play, the value TRUE will be returned. A row of
  813. attackers moves out of play when it gets to the bottom of the screen.
  814. The game should then terminate.
  815.  
  816. #C1,R10
  817. boolean move_attacker_row(~W~Iattacker *nasties~Y~I,~W~Iint rows_of_attackers~Y~I,
  818.                           ~W~Iint cols_of_attackers~Y~I,
  819.                           ~W~Iint *current_row~Y~I)
  820.  
  821. #BO,4,17,78,22,7,1,0,4,0,7
  822. The parameters that move_attacker_row() expects are a pointer to the
  823. array of attackers, the number of rows in the array, the number of
  824. columns in the array, and a pointer to an integer that keeps track of
  825. the row being moved.
  826.  
  827. #C1,R10
  828. ~Y~Iboolean move_attacker_row(attacker *nasties,int rows_of_attackers,
  829.                           int cols_of_attackers,
  830.                           ~W~Iint *current_row~Y~I)
  831.  
  832. #BO,4,17,78,23,7,1,0,5,0,7
  833. The reason that the last parameter is a pointer to an int rather
  834. than just an int is that this function will keep track of which row
  835. should be moved next. When it reaches the last row of attackers, it
  836. starts over. Since we need to be able to change the integer, we need
  837. a pointer to it.
  838.  
  839. #C1,R12
  840.                           ~Y~Iint *current_row)
  841. {
  842. ~W~I    int i,j;
  843.     attacker *temp=nasties+(*current_row * cols_of_attackers);
  844.     static attacker_direction go_to=ATTACKER_RIGHT;
  845.     static int maxy=0;
  846.     boolean still_in_play=TRUE;~Y~I
  847.  
  848. #BO,4,7,78,12,7,1,0,4,0,7
  849. Some variables are declared on the next few lines. The first two, i
  850. and j, are standard loop counters. These are followed by a
  851. declaration of a variable that is a pointer to attackers called
  852. "temp".
  853.  
  854. #C1,R14
  855. ~Y~I    int i,j;
  856.     attacker *temp=nasties+(*current_row * cols_of_attackers);
  857. ~W~I    static attacker_direction go_to=ATTACKER_RIGHT;~Y~I
  858.     static int maxy=0;
  859.     boolean still_in_play=TRUE;
  860.  
  861. #BO,4,6,78,13,7,1,0,6,0,7
  862. This variable declaration is slightly unusual. This line declares the
  863. variable "go_to", which is of type attacker_direction, that is of
  864. storage class static. This means that the variable will "remember"
  865. its value from one invocation of the function to the next. This
  866. variable is used to keep track of which direction the row will move
  867. next, when the attackers change direction.
  868.  
  869. #C1,R16
  870. ~Y~I    static attacker_direction go_to=ATTACKER_RIGHT;
  871. ~W~I    static int maxy=0;~Y~I
  872.  
  873. #BO,4,6,78,9,7,1,0,2,0,7
  874. This line has a variable that keeps track of the maximum number of
  875. scan lines on the screen.
  876.  
  877. #C1,R17
  878. ~Y~I    static int maxy=0;
  879. ~W~I    boolean still_in_play=TRUE;~Y~I
  880.  
  881. #BO,4,6,78,10,7,1,0,3,0,7
  882. The variable on this line tells us whether or not the row has moved
  883. out of bounds. This is the value that will be returned by the
  884. function.
  885.  
  886. #WP
  887. %
  888. #EF
  889. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 48
  890. #HS,1,4,80,25,11,1
  891. #C1,R5
  892.                                  ~W~IListing 8.6 (cont)~Y~I
  893.                                      ATTACKER.C
  894.  
  895. ~W~I    switch(get_attacker_direction(nasties))
  896. ~Y~I    {
  897.         case ATTACKER_LEFT:
  898.             temp=nasties+(*current_row * cols_of_attackers);
  899.             for (i=0;i<cols_of_attackers;i++)
  900.             {
  901.                 if (get_attacker_is_alive(temp))
  902.                 {
  903.                      erase_an_attacker(temp);
  904.  
  905. #C1,R23
  906.                              ~C~IContinued On Next Page~Y~I
  907.  
  908. #BO,4,17,78,22,7,1,0,4,0,7
  909. The real code for this function starts with a switch statement. The
  910. value that is switched on is the current direction of the attacker.
  911. There are cases for all of the valid directions in which an attacker
  912. can move. Let's look at each case in turn.
  913.  
  914. #C1,R8
  915. ~Y~I    switch(get_attacker_direction(nasties))
  916.  
  917. #C1,R11
  918.             ~W~Itemp=nasties+(*current_row * cols_of_attackers);~Y~I
  919.  
  920. #BO,4,17,78,21,7,1,0,3,0,7
  921. If the current direction that the attacker is moving in is left, the
  922. first thing we do is set a pointer to the beginning of the current
  923. row.
  924.  
  925. #C1,R11
  926.             temp=nasties+(~W~I*~Y~Icurrent_row * cols_of_attackers);
  927.  
  928. #BO,4,17,78,21,7,1,0,3,0,7
  929. Don't be confused by the extra * in front of current_row. The * before
  930. the variable current_row does something different than the one between
  931. current_row and cols_of_attackers.
  932.  
  933. #C1,R11
  934.             temp=nasties+(~W~I*current_row ~Y~I* cols_of_attackers);
  935.  
  936. #BO,4,17,78,22,7,1,0,4,0,7
  937. The * before the variable current_row dereferences the pointer to the
  938. integer that contains the current row number. We read this as "the
  939. contents of what the pointer current_row points at."  The * between
  940. current_row and cols_of_attackers is a multiplication.
  941.  
  942. #C1,R11
  943. ~Y~I            temp=nasties+(*current_row * cols_of_attackers);
  944. ~W~I            for (i=0;i<cols_of_attackers;i++)~Y~I
  945.  
  946. #BO,4,17,78,19,7,1,0,1,0,7
  947. The temp pointer is then moved down the row in the for loop.
  948.  
  949. #C1,R12
  950. ~Y~I            for (i=0;i<cols_of_attackers;i++)
  951.             {
  952. ~W~I                if (get_attacker_is_alive(temp))
  953.                 {
  954.                      erase_an_attacker(temp);~Y~I
  955.  
  956. #BO,4,17,78,21,7,1,0,3,0,7
  957. When each attacker in the row is pointed at by temp, it is asked if it
  958. is alive. If it is, its bitmap is erased from its current position on
  959. the screen.
  960.  
  961. #WP
  962. %
  963. #EF
  964. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 49
  965. #HS,1,4,80,25,11,1
  966. #C1,R4
  967.                                  ~W~IListing 8.6 (cont)~Y~I
  968.                                      ATTACKER.C
  969.  
  970. ~W~I                     if (get_attacker_col(temp) -
  971.                          get_attacker_move_increment(temp) <= 0)
  972.                      {
  973.                          set_all_attacker_direction(nasties,
  974.                                                     rows_of_attackers,
  975.                                                     cols_of_attackers,
  976.                                                     ATTACKER_DOWN);
  977. ~Y~I                         go_to=ATTACKER_RIGHT;
  978.                          i=cols_of_attackers;
  979.                          *current_row=rows_of_attackers;
  980.                      }
  981.                      else
  982.                          set_attacker_col(temp,
  983.                                           get_attacker_col(temp) -
  984.                                           get_attacker_move_increment(temp));
  985.  
  986. #C1,R23
  987.                              ~C~IContinued On Next Page~Y~I
  988.  
  989. #BO,4,17,78,22,7,1,0,4,0,7
  990. If the attacker being pointed at is about to move off the left edge
  991. of the screen, the direction of all of the attackers in the row is
  992. set so that they will move downward the next time this function is
  993. called.
  994.  
  995. #C1,R4
  996.                                  ~W~IListing 8.6 (cont)~Y~I
  997.                                      ATTACKER.C
  998.  
  999. ~Y~I                     if (get_attacker_col(temp) -
  1000.                          get_attacker_move_increment(temp) <= 0)
  1001.                      {
  1002.                          set_all_attacker_direction(nasties,
  1003.                                                     rows_of_attackers,
  1004.                                                     cols_of_attackers,
  1005.                                                     ATTACKER_DOWN);
  1006. ~W~I                         go_to=ATTACKER_RIGHT;
  1007.                          i=cols_of_attackers;~Y~I
  1008.  
  1009. #BO,4,17,78,21,7,1,0,3,0,7
  1010. The variable go_to is set so that after the row is moved down, it
  1011. will move to the right. The variable i is given the value of
  1012. cols_of_attackers so that the for loop will terminate.
  1013.  
  1014. #C1,R14
  1015. ~Y~I                         go_to=ATTACKER_RIGHT;
  1016.                          i=cols_of_attackers;
  1017. ~W~I                         *current_row=rows_of_attackers;~Y~I
  1018.  
  1019. #BO,4,7,78,11,7,1,0,3,0,7
  1020. Finally, the contents of the pointer current_row is assigned the
  1021. value of the last row in the array. The reason for this will become
  1022. clear when we discuss the case of attackers moving down.
  1023.  
  1024. #C1,R16
  1025. ~Y~I                         *current_row=rows_of_attackers;
  1026.                      }
  1027. ~W~I                     else
  1028.                          set_attacker_col(temp,
  1029.                                           get_attacker_col(temp) -
  1030.                                           get_attacker_move_increment(temp));
  1031. ~Y~I
  1032.  
  1033. #BO,4,7,78,12,7,1,0,4,0,7
  1034. If the attacker has not moved off the left edge of the screen, the
  1035. column number of the new position of the upper left corner of the
  1036. attacker's bitmap is calculated and assigned to the appropriate
  1037. field in the attacker structure.
  1038.  
  1039. #WP
  1040. %
  1041. #EF
  1042. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 50
  1043. #HS,1,4,80,25,11,1
  1044. #C1,R5
  1045.                                  ~W~IListing 8.6 (cont)~Y~I
  1046.                                      ATTACKER.C
  1047.  
  1048. ~W~I                     draw_an_attacker(temp,COPY_PUT);
  1049.                  }
  1050.                  temp++;~Y~I
  1051.              }
  1052.              break;
  1053.  
  1054. #C1,R23
  1055.                              ~C~IContinued On Next Page~Y~I
  1056.  
  1057. #BO,4,17,78,21,7,1,0,3,0,7
  1058. The attacker is then drawn at the new position. At the end of the
  1059. for loop, the temp pointer is incremented to point at the next
  1060. attacker in the row currently being moved.
  1061.  
  1062. #WP
  1063. %
  1064. #EF
  1065. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 51
  1066. #HS,1,4,80,25,11,1
  1067. #C1,R5
  1068.                                  ~W~IListing 8.6 (cont)~Y~I
  1069.                                      ATTACKER.C
  1070.  
  1071.         case ATTACKER_RIGHT:
  1072. ~W~I            temp=nasties + (*current_row * cols_of_attackers) +
  1073.                  (cols_of_attackers-1);~Y~I
  1074.  
  1075.             for (i=cols_of_attackers-1;i>=0;i--)
  1076.             {
  1077.                 if (get_attacker_is_alive(temp))
  1078.                 {
  1079.                     erase_an_attacker(temp);
  1080.  
  1081. #C1,R23
  1082.                              ~C~IContinued On Next Page~Y~I
  1083.  
  1084. #BO,4,17,78,20,7,1,0,2,0,7
  1085. The logic for moving right is very similar to the logic for moving an
  1086. attacker left. We set temp to point at the end of the current row.
  1087.  
  1088. #C1,R5
  1089.                                  ~W~IListing 8.6 (cont)~Y~I
  1090.                                      ATTACKER.C
  1091.  
  1092.         case ATTACKER_RIGHT:
  1093.             temp=nasties + (*current_row * cols_of_attackers) +
  1094.                  (cols_of_attackers-1);
  1095.  
  1096. ~W~I            for (i=cols_of_attackers-1;i>=0;i--)
  1097.             {
  1098.                 if (get_attacker_is_alive(temp))
  1099.                 {
  1100.                     erase_an_attacker(temp);~Y~I
  1101.  
  1102. #BO,4,17,78,21,7,1,0,3,0,7
  1103. Next we go into a for loop, stepping along the row, erasing each
  1104. attacker, and then testing it to see if it is about to move off the
  1105. right edge of the screen. The test is shown on the next page.
  1106.  
  1107. #WP
  1108. %
  1109. #EF
  1110. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 52
  1111. #HS,1,4,80,25,11,1
  1112. #C1,R4
  1113.                                  ~W~IListing 8.6 (cont)~Y~I
  1114.                                      ATTACKER.C
  1115.  
  1116. ~W~I                    if (get_attacker_col(temp) +
  1117.                         get_attacker_move_increment(temp) +
  1118.                         get_attacker_bitmap_width(temp) >=
  1119.                         getmaxx())
  1120.                     {
  1121.                         set_all_attacker_direction(nasties,
  1122.                                                    rows_of_attackers,
  1123.                                                    cols_of_attackers,
  1124.                                                    ATTACKER_DOWN);
  1125. ~Y~I                        go_to=ATTACKER_LEFT;
  1126.                         i=0;
  1127.                         *current_row=rows_of_attackers;
  1128.                     }
  1129.                     else
  1130.                         set_attacker_col(temp,get_attacker_col(temp) +
  1131.                                          get_attacker_move_increment(temp));
  1132.  
  1133. #C1,R23
  1134.                              ~C~IContinued On Next Page~Y~I
  1135.  
  1136. #BO,4,17,78,20,7,1,0,2,0,7
  1137. If the attacker is about to move off the screen, the direction of all
  1138. of the attackers in the row is set to ATTACKER_DOWN.
  1139.  
  1140. #C1,R4
  1141.                                  ~W~IListing 8.6 (cont)~Y~I
  1142.                                      ATTACKER.C
  1143.  
  1144. ~Y~I                    if (get_attacker_col(temp) +
  1145.                         get_attacker_move_increment(temp) +
  1146.                         get_attacker_bitmap_width(temp) >=
  1147.                         getmaxx())
  1148.                     {
  1149.                         set_all_attacker_direction(nasties,
  1150.                                                    rows_of_attackers,
  1151.                                                    cols_of_attackers,
  1152.                                                    ATTACKER_DOWN);
  1153. ~W~I                        go_to=ATTACKER_LEFT;~Y~I
  1154.  
  1155. #BO,4,7,78,10,7,1,0,2,0,7
  1156. The variable go_to is set to ATTACKER_LEFT so that the attackers will
  1157. move left after they have moved down.
  1158.  
  1159. #C1,R16
  1160. ~Y~I                        go_to=ATTACKER_LEFT;
  1161. ~W~I                        i=0;
  1162.                         *current_row=rows_of_attackers;~Y~I
  1163.  
  1164. #BO,4,7,78,11,7,1,0,3,0,7
  1165. The loop counter i is set to 0 so that the loop will terminate, and
  1166. the contents of the pointer current_row is assigned the value of the
  1167. last row in the array.
  1168.  
  1169. #C1,R17
  1170. ~Y~I                        i=0;
  1171.                         *current_row=rows_of_attackers;
  1172.                     }
  1173. ~W~I                    else
  1174.                         set_attacker_col(temp,get_attacker_col(temp) +
  1175.                                          get_attacker_move_increment(temp));
  1176. ~Y~I
  1177.  
  1178. #BO,4,7,78,10,7,1,0,2,0,7
  1179. If the attacker hasn't reached the right edge of the screen, the
  1180. column number of its upper left corner is adjusted to the right.
  1181.  
  1182. #WP
  1183. %
  1184. #EF
  1185. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 53
  1186. #HS,1,4,80,25,11,1
  1187. #C1,R5
  1188.                                  ~W~IListing 8.6 (cont)~Y~I
  1189.                                      ATTACKER.C
  1190. ~W~I
  1191.                     draw_an_attacker(temp,COPY_PUT);
  1192.                 }
  1193.                 temp--;
  1194. ~Y~I            }
  1195.             break;
  1196.  
  1197. #C1,R23
  1198.                              ~C~IContinued On Next Page~Y~I
  1199. #BO,4,17,78,20,7,1,0,2,0,7
  1200. The current attacker is then drawn, and the temp pointer is
  1201. decremented to point at the next attacker.
  1202.  
  1203. #BO,4,16,78,23,7,1,0,6,0,7
  1204. When moving an attacker, we've always got to move the ones on the
  1205. leading edge of the array first. So when we move the attackers left,
  1206. we start with the leftmost attackers and work toward the right. When
  1207. moving them right, we start with the rightmost attackers and work to
  1208. the left. When moving down, we start with the lowest attackers and
  1209. work upward.
  1210.  
  1211. #WP
  1212. %
  1213. #EF
  1214. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 54
  1215. #HS,1,4,80,25,11,1
  1216. #C1,R4
  1217.                                  ~W~IListing 8.6 (cont)~Y~I
  1218.                                      ATTACKER.C
  1219.  
  1220.  
  1221.         case ATTACKER_DOWN:
  1222. ~W~I            temp=nasties+(*current_row * cols_of_attackers);
  1223.  
  1224. ~Y~I            for (i=0;i<cols_of_attackers;i++)
  1225.             {
  1226.                 if (get_attacker_is_alive(temp))
  1227.                 {
  1228.                     erase_an_attacker(temp);
  1229.                     set_attacker_row(temp,
  1230.                                      get_attacker_row(temp) +
  1231.                                      get_attacker_move_increment(temp));
  1232.                     draw_an_attacker(temp,COPY_PUT);
  1233.                 }
  1234.                 temp++;
  1235.             }
  1236.  
  1237. #C1,R23
  1238.                              ~C~IContinued On Next Page~Y~I
  1239.  
  1240. #BO,4,17,78,21,7,1,0,3,0,7
  1241. Moving downward is a very different task than moving left or right.
  1242. First, we set a pointer to point at the beginning of the row being
  1243. moved.
  1244.  
  1245. #C1,R4
  1246.                                  ~W~IListing 8.6 (cont)~Y~I
  1247.                                      ATTACKER.C
  1248.  
  1249.  
  1250.         case ATTACKER_DOWN:
  1251.             temp=nasties+(*current_row * cols_of_attackers);
  1252.  
  1253. ~W~I            for (i=0;i<cols_of_attackers;i++)
  1254.             {
  1255.                 if (get_attacker_is_alive(temp))
  1256.                 {
  1257.                     erase_an_attacker(temp);
  1258.                     set_attacker_row(temp,
  1259.                                      get_attacker_row(temp) +
  1260.                                      get_attacker_move_increment(temp));
  1261.                     draw_an_attacker(temp,COPY_PUT);
  1262.                 }
  1263.                 temp++;
  1264.             }
  1265. ~Y~I
  1266.  
  1267. #BO,4,5,78,9,7,1,0,3,0,7
  1268. Then we enter a for loop and ask each attacker if it's alive. If it
  1269. is, it is erased, and its new position is set. The attacker is then
  1270. drawn at its new position.
  1271.  
  1272. #WP
  1273. %
  1274. #EF
  1275. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 55
  1276. #HS,1,4,80,25,11,1
  1277. #C1,R5
  1278.                                  ~W~IListing 8.6 (cont)~Y~I
  1279.                                      ATTACKER.C
  1280.  
  1281.  
  1282. ~W~I            if (*current_row<=0)
  1283.                 set_all_attacker_direction(nasties,
  1284.                                            rows_of_attackers,
  1285.                                            cols_of_attackers,
  1286.                                            go_to);
  1287.  
  1288. ~Y~I            if (maxy==0)
  1289.                 maxy=getmaxy();
  1290.  
  1291. #C1,R23
  1292.                              ~C~IContinued On Next Page~Y~I
  1293.  
  1294. #BO,4,17,78,21,7,1,0,3,0,7
  1295. Once the current row has been moved, we test to see if the current
  1296. row is less than or equal to zero. If it is, the direction of all of
  1297. the attackers is set to whatever the variable go_to contains.
  1298.  
  1299. #BO,4,17,78,21,7,1,0,3,0,7
  1300. By the way, the actual test here only needs to see if the current row
  1301. is equal to zero. However, I made it less than or equal to just in
  1302. case there was some kind of error in the program. It's a safer test.
  1303.  
  1304. #C1,R5
  1305.                                  ~W~IListing 8.6 (cont)~Y~I
  1306.                                      ATTACKER.C
  1307.  
  1308.  
  1309. ~Y~I            if (*current_row<=0)
  1310.                 set_all_attacker_direction(nasties,
  1311.                                            rows_of_attackers,
  1312.                                            cols_of_attackers,
  1313.                                            go_to);
  1314.  
  1315. ~W~I            if (maxy==0)
  1316.                 maxy=getmaxy();
  1317. ~Y~I
  1318.  
  1319. #BO,4,7,78,11,7,1,0,3,0,7
  1320. The variable maxy is set to the maximum number of lines on the screen.
  1321. This is only done once. Because maxy is a static variable, it will
  1322. retain its value between invocations of this function.
  1323.  
  1324. #WP
  1325. %
  1326. #EF
  1327. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 56
  1328. #HS,1,4,80,25,11,1
  1329. #C1,R4
  1330.                                  ~W~IListing 8.6 (cont)~Y~I
  1331.                                      ATTACKER.C
  1332.  
  1333.             for (i=rows_of_attackers-1;(i>=0) && (still_in_play);i--)
  1334.             {
  1335.                 temp=nasties+(i * cols_of_attackers);
  1336.                 for (j=0;(j<cols_of_attackers) && (still_in_play);j++)
  1337.                 {
  1338.                     if ((get_attacker_is_alive(temp)) &&
  1339.                         (get_attacker_row(temp) +
  1340.                         (2 * get_attacker_bitmap_height(temp)) >= maxy))
  1341.                     {
  1342.                         still_in_play=FALSE;
  1343.                     }
  1344.                     temp++;
  1345.                 }
  1346.             }
  1347.  
  1348.             break;
  1349.  
  1350. #C1,R23
  1351.                              ~C~IContinued On Next Page~Y~I
  1352.  
  1353. #BO,4,17,78,23,7,1,0,5,0,7
  1354. Next, a pair of nested for loops are entered. Each attacker is
  1355. tested to see if it has gone off of the bottom of the screen, If it
  1356. has, the variable still_in_play is set to FALSE, indicating that the
  1357. player has lost this round. If it hasn't, still_in_play will retain
  1358. its value of TRUE, and the game will continue.
  1359.  
  1360. #WP
  1361. %
  1362. #EF
  1363. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 57
  1364. #HS,1,4,80,25,11,1
  1365. #C1,R5
  1366.                                  ~W~IListing 8.6 (cont)~Y~I
  1367.                                      ATTACKER.C
  1368.  
  1369.     }
  1370.     ~W~Ireturn(still_in_play);~Y~I
  1371. }
  1372.  
  1373. /*---------------------------end move_attackers-----------------------------*/
  1374.  
  1375.  
  1376. #C1,R23
  1377.                              ~C~IContinued On Next Page~Y~I
  1378.  
  1379. #BO,4,17,78,19,7,1,0,2,0,7
  1380. The function then terminates by returning the value still_in_play.
  1381.  
  1382. #WP
  1383. %
  1384. #EF
  1385. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 58
  1386. #HS,1,4,80,25,11,1
  1387. #C1,R5
  1388.                                  ~W~IListing 8.6 (cont)~Y~I
  1389.                                      ATTACKER.C
  1390.  
  1391.  
  1392. /*---------------------------shoot_attacker_gun-----------------------------*/
  1393.  
  1394. ~W~Ivoid shoot_attacker_gun(attacker *nasties,int rows_of_attackers,
  1395.                         int cols_of_attackers)
  1396. ~Y~I{
  1397.     int i,j;
  1398.     attacker *temp;
  1399.     boolean fired;
  1400.     static int last_fired_row=0,last_fired_col=0;
  1401.  
  1402. #C1,R23
  1403.                              ~C~IContinued On Next Page~Y~I
  1404.  
  1405. #BO,4,17,78,20,7,1,0,2,0,7
  1406. Attackers will attempt to shoot at the player from time to time. This
  1407. action is handled by the function shoot_attacker_gun().
  1408.  
  1409. #C1,R5
  1410.                                  ~W~IListing 8.6 (cont)~Y~I
  1411.                                      ATTACKER.C
  1412.  
  1413.  
  1414. /*---------------------------shoot_attacker_gun-----------------------------*/
  1415.  
  1416. ~W~Ivoid ~Y~Ishoot_attacker_gun(attacker *nasties,int rows_of_attackers,
  1417.                         int cols_of_attackers)
  1418.  
  1419. #BO,4,17,78,19,7,1,0,2,0,7
  1420. This function does not return a value.
  1421.  
  1422. #C1,R5
  1423.                                  ~W~IListing 8.6 (cont)~Y~I
  1424.                                      ATTACKER.C
  1425.  
  1426.  
  1427. /*---------------------------shoot_attacker_gun-----------------------------*/
  1428.  
  1429. void shoot_attacker_gun(~W~Iattacker *nasties~Y~I,~W~Iint rows_of_attackers~Y~I,
  1430.                         ~W~Iint cols_of_attackers~Y~I)
  1431.  
  1432. #BO,4,17,78,21,7,1,0,3,0,7
  1433. The only parameters it needs are a pointer to the array of attackers,
  1434. the number of rows in the array, and the number of columns in the
  1435. array.
  1436.  
  1437. #C1,R5
  1438.                                  ~W~IListing 8.6 (cont)~Y~I
  1439.                                      ATTACKER.C
  1440.  
  1441.  
  1442. /*---------------------------shoot_attacker_gun-----------------------------*/
  1443.  
  1444. void shoot_attacker_gun(attacker *nasties,int rows_of_attackers,
  1445.                         int cols_of_attackers)
  1446.  
  1447. #BO,4,17,78,23,7,1,0,5,0,7
  1448. This function is rather unusual in that it must not only fire the
  1449. bullet of one of the attackers, it must keep track of which attacker
  1450. was the last to fire. We don't want one or two attackers to be the
  1451. only ones that are shooting at the player. It would be nice if there
  1452. was a fairly even firing distribution.
  1453.  
  1454. #BO,4,14,78,23,7,1,0,8,0,7
  1455. We can achieve this by cycling through the array of attackers. The
  1456. first time we find an attacker that is at the bottom of its row and
  1457. doesn't currently have a bullet in flight, we tell it to shoot. We
  1458. then have to keep track of which attacker was the last to shoot. The
  1459. next time this function is called, we'll start cycling through the
  1460. array with the  attacker that is immediately after the one that last
  1461. shot its bullet. The logic of shoot_attacker_gun() follows this
  1462. pattern.
  1463.  
  1464. #C1,R14
  1465. ~W~I    int i,j;
  1466.     attacker *temp;
  1467.     boolean fired;
  1468.     static int last_fired_row=0,last_fired_col=0;~Y~I
  1469.  
  1470. #BO,4,17,78,19,7,1,0,2,0,7
  1471. As always, we start the function by declaring all local variables.
  1472.  
  1473. #C1,R14
  1474. ~Y~I    int i,j;
  1475.     attacker *temp;
  1476.     boolean fired;
  1477. ~W~I    static int last_fired_row=0,last_fired_col=0;~Y~I
  1478.  
  1479. #BO,4,7,78,12,7,1,0,4,0,7
  1480. The only thing significant in this part of the function is that the
  1481. variables last_fired_row and last_fired_col are declared as static.
  1482. These variables will be used to remember which attacker fired last,
  1483. that's why they need to be static.
  1484.  
  1485. #WP
  1486. %
  1487. #EF
  1488. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 59
  1489. #HS,1,4,80,25,11,1
  1490. #C1,R5
  1491.                                  ~W~IListing 8.6 (cont)~Y~I
  1492.                                      ATTACKER.C
  1493.  
  1494. ~W~I    if (last_fired_col>=cols_of_attackers)
  1495.     {
  1496.         last_fired_col=0;
  1497.         last_fired_row++;
  1498.     }
  1499. ~Y~I    if (last_fired_row>=rows_of_attackers)
  1500.         last_fired_row=0;
  1501.  
  1502.     for (i=last_fired_row,fired=FALSE;(i<rows_of_attackers) && (!fired);i++)
  1503.     {
  1504.         for (j=last_fired_col;(j<cols_of_attackers) && (!fired);j++)
  1505.         {
  1506.             temp=nasties+(i*cols_of_attackers)+j;
  1507.  
  1508. #C1,R23
  1509.                              ~C~IContinued On Next Page~Y~I
  1510.  
  1511.  
  1512.  
  1513. #BO,4,17,78,21,7,1,0,3,0,7
  1514. The first thing that happens in the function is to check to see if
  1515. the variable last_fired_col was incremented beyond the last column.
  1516. If so, it is reset to column zero.
  1517.  
  1518. #C1,R8
  1519. ~Y~I    if (last_fired_col>=cols_of_attackers)
  1520.     {
  1521.         last_fired_col=0;
  1522.         last_fired_row++;
  1523.     }
  1524. ~W~I    if (last_fired_row>=rows_of_attackers)
  1525.         last_fired_row=0;
  1526.  
  1527. #BO,4,17,78,21,7,1,0,3,0,7
  1528. Next, we test to see if last_fired_row has been incremented beyond
  1529. the number of rows in the array. If that's the case, we start over
  1530. again at the first row.
  1531.  
  1532. #C1,R13
  1533. ~Y~I    if (last_fired_row>=rows_of_attackers)
  1534.         last_fired_row=0;
  1535. ~W~I
  1536.     for (i=last_fired_row,fired=FALSE;(i<rows_of_attackers) && (!fired);i++)
  1537.     {
  1538.         for (j=last_fired_col;(j<cols_of_attackers) && (!fired);j++)
  1539. ~Y~I
  1540.  
  1541. #BO,4,7,78,12,7,1,0,4,0,7
  1542. The function then goes into a pair of nested for loops that move
  1543. through the array and ask each attacker three things: 1) are you
  1544. alive, 2) are you the in a position to shoot, and 3) is your bullet
  1545. currently not in flight.
  1546.  
  1547.  
  1548. #WP
  1549. %
  1550. #EF
  1551. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 60
  1552. #HS,1,4,80,25,11,1
  1553. #C1,R5
  1554.                                  ~W~IListing 8.6 (cont)~Y~I
  1555.                                      ATTACKER.C
  1556.  
  1557.             if ((get_attacker_is_alive(temp)) &&
  1558.                 (get_attacker_at_edge(temp)) &&
  1559.                 (!get_attacker_has_bullet(temp)))
  1560.             {
  1561. ~W~I                phew();
  1562.  
  1563.                 set_attacker_bullet_row(temp,
  1564.                                         get_attacker_row(temp) +
  1565.                                         get_attacker_bitmap_height(temp) + 3);
  1566. ~Y~I
  1567.                 set_attacker_bullet_col(temp,
  1568.                                         get_attacker_col(temp) +
  1569.                                         (get_attacker_bitmap_width(temp)/2));
  1570.  
  1571. #C1,R23
  1572.                              ~C~IContinued On Next Page~Y~I
  1573.  
  1574.  
  1575. #BO,4,17,78,20,7,1,0,2,0,7
  1576. If these three conditions are met, then a noise is made with a call
  1577. to the function phew(). The position of the attacker's bullet is set.
  1578.  
  1579.  
  1580. #WP
  1581. %
  1582. #EF
  1583. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 61
  1584. #HS,1,4,80,25,11,1
  1585. #C1,R5
  1586.                                  ~W~IListing 8.6 (cont)~Y~I
  1587.                                      ATTACKER.C
  1588.  
  1589. ~W~I                set_attacker_bullet(temp,TRUE);
  1590.                 set_attacker_bullet_direction(temp,BULLET_DOWN);
  1591.                 set_attacker_bullet_color(temp,COLOR1);
  1592.                 draw_bullet(&get_attacker_bullet(temp));
  1593. ~Y~I                last_fired_row=i;
  1594.                 last_fired_col=j+1;
  1595.                 fired=TRUE;
  1596.             }
  1597.         }
  1598.     }
  1599. }
  1600.  
  1601. /*-------------------------end shoot_attacker_gun---------------------------*/
  1602.  
  1603.  
  1604. #C1,R23
  1605.                              ~C~IContinued On Next Page~Y~I
  1606.  
  1607.  
  1608. #BO,4,17,78,20,7,1,0,2,0,7
  1609. The attacker is told that is has a bullet in flight. The bullet's color
  1610. and direction are set and the bullet is drawn.
  1611.  
  1612. #C1,R5
  1613.                                  ~W~IListing 8.6 (cont)~Y~I
  1614.                                      ATTACKER.C
  1615.  
  1616. ~Y~I                set_attacker_bullet(temp,TRUE);
  1617.                 set_attacker_bullet_direction(temp,BULLET_DOWN);
  1618.                 set_attacker_bullet_color(temp,COLOR1);
  1619.                 draw_bullet(&get_attacker_bullet(temp));
  1620. ~W~I                last_fired_row=i;
  1621.                 last_fired_col=j+1;
  1622. ~Y~I
  1623.  
  1624.  
  1625. #BO,4,17,78,20,7,1,0,2,0,7
  1626. The row and column number of the next attacker that might be able to
  1627. fire are stored in last_fired_row and last_fired_col.
  1628.  
  1629. #C1,R12
  1630. ~Y~I                last_fired_row=i;
  1631.                 last_fired_col=j+1;
  1632. ~W~I                fired=TRUE;
  1633.  
  1634. #BO,4,17,78,19,7,1,0,1,0,7
  1635. The variable fired is set to TRUE so that the loops will terminate.
  1636.  
  1637. #WP
  1638. %
  1639. #EF
  1640. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 62
  1641. #HS,1,4,80,25,11,1
  1642. #C1,R5
  1643.                                  ~W~IListing 8.6 (cont)~Y~I
  1644.                                      ATTACKER.C
  1645.  
  1646. /*----------------------------attackers_all_dead----------------------------*/
  1647. /*
  1648. ~W~IWARNING: This function has multiple exit points.~Y~I
  1649. */
  1650.  
  1651. boolean attackers_all_dead(attacker *thugs,int rows_of_attackers,
  1652.                            int cols_of_attackers)
  1653. {
  1654.     int i,j;
  1655.     attacker *temp=thugs;
  1656.  
  1657. #C1,R23
  1658.                              ~C~IContinued On Next Page~Y~I
  1659.  
  1660. #BO,4,17,78,21,7,1,0,3,0,7
  1661. Back in Chapter 5, I mentioned that we would use structured
  1662. programming techniques to develop the games for this book. So far, we
  1663. have followed those tenants almost religiously.
  1664.  
  1665. #BO,4,17,78,20,7,1,0,2,0,7
  1666. In the function attackers_all_dead(), I've deviated from that in one
  1667. important respect. This function has multiple exit points.
  1668.  
  1669. #BO,4,17,78,21,7,1,0,3,0,7
  1670. GASP! Yes, it's true. Normally, it's extremely unwise to have more
  1671. than one entry or exit point from a given module of code. There is
  1672. only one reason I didn't stick to that for this function - speed.
  1673.  
  1674. #BO,4,17,78,22,7,1,0,4,0,7
  1675. After developing Space Attackers, I used Turbo Profiler, a Borland
  1676. product that gives information about program execution, to see where
  1677. in the code the game was spending most of its time and which
  1678. functions were called the most.
  1679.  
  1680. #BO,4,16,78,23,7,1,0,6,0,7
  1681. I found that attackers_all_dead() was one of the most frequently
  1682. called functions in the program, and that it needed to be very, very
  1683. efficient to get good performance out of the game. As a result, I went
  1684. back and modified it so that it could return from more than one spot.
  1685. Having multiple exits improved the performance of this function
  1686. dramatically. Therefore, I left it as is.
  1687.  
  1688. #BO,4,17,78,22,7,1,0,4,0,7
  1689. Notice, however, that I have documented the fact that this function has
  1690. multiple exits. There is a clear warning at the beginning of the
  1691. function, and we'll see another at the second exit point (which is
  1692. shown on the next page).
  1693.  
  1694. #C1,R5
  1695.                                  ~W~IListing 8.6 (cont)~Y~I
  1696.                                      ATTACKER.C
  1697.  
  1698. /*----------------------------attackers_all_dead----------------------------*/
  1699. /*
  1700. ~Y~IWARNING: This function has multiple exit points.
  1701.  
  1702. #C1,R13
  1703. ~W~Iboolean ~Y~Iattackers_all_dead(attacker *thugs,int rows_of_attackers,
  1704.                            int cols_of_attackers)
  1705. #BO,4,17,78,20,7,1,0,2,0,7
  1706. Other than that, this function is not unusual or complicated. It
  1707. returns TRUE if the attackers are indeed all dead, and FALSE if not.
  1708.  
  1709. #C1,R13
  1710. ~Y~Iboolean attackers_all_dead(~W~Iattacker *thugs~Y~I,~W~Iint rows_of_attackers~Y~I,
  1711.                            ~W~Iint cols_of_attackers~Y~I)
  1712.  
  1713. #BO,4,17,78,20,7,1,0,2,0,7
  1714. There are only three parameters, a pointer to the array of attackers,
  1715. the number of rows in the array, and the number of columns.
  1716.  
  1717. #WP
  1718. %
  1719. #EF
  1720. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 63
  1721. #HS,1,4,80,25,11,1
  1722. #C1,R5
  1723.                                  ~W~IListing 8.6 (cont)~Y~I
  1724.                                      ATTACKER.C
  1725.  
  1726.     for (i=0;i<rows_of_attackers;i++)
  1727.     {
  1728.         for (j=0;j<cols_of_attackers;j++)
  1729.         {
  1730.             if (get_attacker_is_alive(temp))
  1731.                 return(FALSE);                   /* EXIT POINT */
  1732.             temp++;
  1733.         }
  1734.     }
  1735.     return(TRUE);
  1736. }
  1737.  
  1738. /*--------------------------end attackers_all_dead--------------------------*/
  1739.  
  1740. #C1,R23
  1741.                              ~C~IContinued On Next Page~Y~I
  1742.  
  1743. #BO,4,17,78,21,7,1,0,3,0,7
  1744. Two nested for loops are entered in which each attacker is asked if it
  1745. is alive. As soon as one says yes, the function returns FALSE. If the
  1746. loops execute to completion, TRUE is returned.
  1747.  
  1748.  
  1749. #WP
  1750. %
  1751. #EF
  1752. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 64
  1753. #HS,1,4,80,25,11,1
  1754. #C1,R5
  1755.                                  ~W~IListing 8.6 (cont)~Y~I
  1756.                                      ATTACKER.C
  1757.  
  1758. /*------------------------set_all_attacker_direction------------------------*/
  1759.  
  1760. static ~W~Ivoid ~Y~Iset_all_attacker_direction(attacker *thugs,int rows_of_attackers,
  1761.                                        int cols_of_attackers,
  1762.                                        attacker_direction dir)
  1763. {
  1764.     int i,j;
  1765.     attacker *temp=thugs;
  1766.  
  1767. #C1,R23
  1768.                              ~C~IContinued On Next Page~Y~I
  1769.  
  1770. #BO,4,17,78,20,7,1,0,2,0,7
  1771. The function set_all_attacker_direction() is logically very similar
  1772. to attackers_all_dead(). There is no value returned.
  1773.  
  1774. #C1,R10
  1775. ~W~Istatic ~Y~Ivoid set_all_attacker_direction(attacker *thugs,int rows_of_attackers,
  1776.  
  1777. #BO,4,17,78,23,7,1,0,5,0,7
  1778. The only additional thing that is at all worth discussing about this
  1779. function is the fact that it is of storage class static. Of course,
  1780. that means that this function can only be called by other functions
  1781. in ATTACKER.C. As previously mentioned, this is done for
  1782. implementation hiding.
  1783.  
  1784. #WP
  1785. %
  1786. #EF
  1787. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 65
  1788. #HS,1,4,80,25,11,1
  1789. #C1,R5
  1790.                                  ~W~IListing 8.6 (cont)~Y~I
  1791.                                      ATTACKER.C
  1792.  
  1793.     for (i=0;i<rows_of_attackers;i++)
  1794.     {
  1795.         for (j=0;j<cols_of_attackers;j++)
  1796.         {
  1797.             set_attacker_direction(temp,dir);
  1798.             temp++;
  1799.         }
  1800.     }
  1801. }
  1802.  
  1803. /*----------------------end set_all_attacker_direction----------------------*/
  1804.  
  1805. #C1,R23
  1806.                              ~C~IContinued On Next Page~Y~I
  1807.  
  1808.  
  1809. #BO,4,17,78,22,7,1,0,4,0,7
  1810. The function moves through the array of attackers in exactly the
  1811. same way that attackers_all_dead() did. Instead of asking each
  1812. attacker if it is alive, it tells each attacker what direction to
  1813. move next.
  1814.  
  1815. #WP
  1816. %
  1817. #EF
  1818. #T15,1,Chapter 8     Implementing Space Attackers   Part I  Pg. 66
  1819. #HS,1,4,80,25,11,1
  1820. #C1,R5
  1821.                                  ~W~IListing 8.6 (cont)~Y~I
  1822.                                      ATTACKER.C
  1823.  
  1824. /*--------------------------erase_an_attacker-------------------------------*/
  1825.  
  1826. void erase_an_attacker(attacker *thug)
  1827. {
  1828.  
  1829.     setfillstyle(EMPTY_FILL,0);
  1830.     bar(get_attacker_col(thug),get_attacker_row(thug),
  1831.         get_attacker_col(thug)+get_attacker_bitmap_width(thug),
  1832.         get_attacker_row(thug)+get_attacker_bitmap_height(thug));
  1833.  
  1834. }
  1835.  
  1836. /*------------------------end erase_an_attacker-----------------------------*/
  1837. /*---------------------------end attacker.c---------------------------------*/
  1838.  
  1839. #BO,4,17,78,20,7,1,0,2,0,7
  1840. The last function in ATTACKER.C is erase_an_attacker(). It uses the
  1841. BGI to draw a box of blank pixels over the image of an attacker.
  1842.  
  1843. #C1,R13
  1844. ~W~I    setfillstyle(EMPTY_FILL,0);~Y~I
  1845.  
  1846. #BO,4,17,78,20,7,1,0,2,0,7
  1847. The function setfillstyle() is called to tell the BGI to do an empty
  1848. fill. That is, fill with the background color.
  1849.  
  1850. #C1,R13
  1851. ~Y~I    setfillstyle(EMPTY_FILL,0);
  1852. ~W~I    bar(get_attacker_col(thug),get_attacker_row(thug),
  1853.         get_attacker_col(thug)+get_attacker_bitmap_width(thug),
  1854.         get_attacker_row(thug)+get_attacker_bitmap_height(thug));~Y~I
  1855.  
  1856. #BO,4,17,78,21,7,1,0,3,0,7
  1857. The bar() function is called to draw a rectangle at the location on
  1858. the screen of the attacker's bitmap. The rectangle is the same height
  1859. and width as the bitmap, so it covers the image completely.
  1860. #WP
  1861. #X